<?

/** dzkone readset functionality.
 *
 *  This collection of functions (libary) is licensed under GPL2.
 *  See LICENSE or www.gnu.org for more details.
 *
 *  @author Jyry Kuukkanen
 *  $Id: dzkone_read.php,v 1.6 2005/11/01 12:59:05 jyry Exp $
 */

/* Include files needed */
include_once("sodebug.php");


/** Reads in a set
 *  @param dzKone $Kone dzKone object to operate with.
 *  @param bool $Lock When set, tries locking the set before reading.
 *  @return bool Returns true(1) on success, false(1) on error.
 */
function __dzkone__readSet(&$Kone, $Lock = 0) {
    include("sodebug.inc");
    soDebug("dzKone->__readSet($Lock): enter, struct contains ".
            $Kone->__Struct->dump(), SOD_DET);

    $Kone->__setLockParams();
    if ($Lock) {
        include_once("dzkone_lock.php");
        if (!__dzkone__lockSet($Kone, SOLM_NORMAL)) {
            soDebug("dzKone->__readSet($Lock): locking error!", SOD_LO);
            return 0; // <-- EXIT
        };
    }; // if lock

    /* Locks sorted, proceed to actual read process */
    $Kone->__Soda->clear();

    /* this is to store arrays of datacols and wherecols and
     * wherevals for soDa */
    $tables = $Kone->__getColsByTable();

    /* ready to run -- empty taffel for results */
    $Kone->__Purkki->emptyStore(TAFFEL);

    /* form soDa for each table */
    $keys = $tables->getkeys();
    foreach ($keys as $key) {
        $soda = $tables->getitem($key);
        $allcols = array_merge($soda["datacols"],
                               $soda["wherecols"],
                               $soda["ordercols"]);
        $Kone->__Soda->clear();
        $Kone->__Soda->setAction(SODA_SELECT);
        $Kone->__Soda->setTable($key, 1);
        $Kone->__Soda->setSection(SODA_DATA, $allcols);
        $Kone->__Soda->setSection(SODA_WHERE,
                                  $soda["wherecols"],
                                  $soda["wherevals"]);
        $Kone->__Soda->setSection(SODA_ORDER,
                                  $soda["ordercols"]);

        /* run the sql statement for a table */
        $sql_result = $Kone->__Soda->run();

        /* handle the result for each table back to columns */
        if ($sql_result) {
            foreach ($allcols as $datacol) {
                $Kone->__Purkki->setStoreCol(TAFFEL, $datacol,
                    $Kone->__Soda->Results->getCol($datacol));
            }; // foreach
        } else {
            /* Stop reading rest of the tables and exit on error */
            if ($Lock) __dzkone__lockSet($Kone, SOLM_UNLOCK);
            $Kone->__OutItu->setBlockItem(DZI_CONTROL, DZK_RESULT,
                                          DZR_READ_ERROR);
            $Kone->__OutItu->setBlockItem(DZI_DATA, DZK_SQL,
                                          $Kone->__Soda->Clause);
            return 0; // <-- EXIT
        }; // else if $result

    }; // foreach table

    /* This point is only reached when no errors occured during read */
    $Kone->__OutItu->setBlockItem(DZI_CONTROL, DZK_RESULT, DZR_OK);

    if (($Lock) && ($Kone->__Struct->_Name != "")) {
        $cache_filename = $Kone->__getCacheFileName($soda["wherevals"]);
        soDebug("dzkone->__readSet: writing to cache file ".
                "'$cache_filename'", SOD_LO);
        if ($cache_filename != "") {
            $os = new soOutputStream($cache_filename,
                                    $Kone->__Purkki->getStore(TAFFEL));
        };
    }; // if lock & struct name

    __dzkone__readPseudoCols($Kone);
    return 1; // <-- EXIT
} // __dzkone__readSet


/** Reads data to pseudo table columns.
 *  This is called by __readSet. It checks for any pseudo table columns and
 *  if any of them is dependend on just read column, the __fetch method is
 *  then called for each row.
 *  @param dzKone $Kone dzKone object to operate with.
 *  @return bool Returns true(1) on success or false(0) on any bizard error.
 */
function __dzkone__readPseudoCols(&$Kone) {
    include("sodebug.inc");
    soDebug("__dzkone__readPseudoCols entered", SOD_DET);

    /* due to some very strange php feature, calling setStoreCol
     * inside foreach loop, it clears the the whole store,
     * hence results are 1st store to $result and then copied
     * to the TAFFEL */
    $result = new soSet();

    /* loop each column */
    $colnames = $Kone->__Struct->__Cols->getKeys();
    foreach ($colnames as $colname) {

        /* v- [0] = table name, [1] = col name */
        $split = soSplitStr($colname, ".", 1, 0);
        if (!count($split)) return 0; // <-- EXIT

        if ($split[0] == DZPSEUDO) {
            $col = $Kone->__Struct->__Cols->getItem($colname);
            if ($col->Fetching != "") {
                $result->addItem($colname,
                    __dzkone__readPseudoColLoop($Kone, $col->Fetching));
            }; // if $col->Fetching
        }; // if pseudo
    }; // foreach $colname

    /* finishing up php feature roundwork */
    $keys = $result->getKeys();
    $kcount = count($keys);
    for ($k = 0; $k < $kcount; $k++) {
        $set = $result->getItem($keys[$k]);
        $Kone->__Purkki->setStoreCol(TAFFEL, $keys[$k], $set);
    }; // for $k

    return 1;
} // __dzkone__readPseudoCols


/** Reads all values for a pseudo column.
 *  @param dzKone $Kone dzKone object to operate with.
 *  @param string $Fetching Fetching declaration.
 *  @return array/any Returns return values.
 */
function __dzkone__readPseudoColLoop(&$Kone, $Fetching) {
    include("sodebug.inc");
    soDebug("__dzkone__readPseudoColLoop: $Fetching", SOD_DET);

    /* Explode to array where [0]=src col, [1]=table, [2]=key col(s),
     * [3]=data col */
    $fetch = soExplode($Fetching, ",");

    /* source cols needs to be stripped for $ prefix */
    $src_cols = soExplode($fetch[0], '+');
    foreach ($src_cols as $key => $value) {
        $src_cols[$key] = $Kone->__Struct->findCol(substr($value, 1));
    }; // foreach

    /* Instead of doing fetch for every row possible, results by
    * key values are cached. */
    $cache = &new soArraySet();

    $result = array();

    /* Get source col values, ignore the possible explicit rowno.
     * specification (colname#rowno) for now */
    $src_vals = array();
    $scount = 0;
    foreach ($src_cols as $src_col) {
        $key = soExtractVal($src_col, '#', 1);
        $src_vals[$key] = $Kone->__Purkki->getStoreCol(TAFFEL, $key);
        $scount = max($scount, count($src_vals[$key]));
    };
    $fetch_col = soExtractVal($fetch[3], "+", 1);
    for ($s = 0; $s < $scount; $s++) {
        include_once("dzkone_fetch.php");
        $vals = array();
        foreach ($src_cols as $src_col) {
            $key = soExtractVal($src_col, '#', 1);
            if ($pos = soExtractVal($src_col, '#', 2)) {
                $pos--;
            } else {
                $pos = $s;
            };
            $vals[] = $src_vals[$key][$pos];
        }; // foreach
        $values = __dzkone__fetch_sub($Kone->__Soda, $fetch[1], $fetch[2],
                                      $vals,
                                      $fetch_col, $cache);
        $result[] = $values->getArrayItem($fetch_col, 0);
    }; // for $s

    return $result;
} // __dzkone__readPseudoColLoop


?>
